package com.ztgf.sys.service;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.ztgf.sys.common.config.YmlConfig;
import com.ztgf.sys.mapper.SysRoleMenuRelationMapper;
import com.ztgf.sys.models.bo.SysRoleMenuRelationBO;
import com.ztgf.sys.models.bo.SysRoleMenuRelationSaveBO;
import com.ztgf.sys.models.constant.SysConstant;
import com.ztgf.sys.models.dto.SysMenuDTO;
import com.ztgf.sys.models.dto.SysRoleDTO;
import com.ztgf.sys.models.dto.SysRoleMenuRelationDTO;
import com.ztgf.sys.models.service.ISysRoleMenuRelationService;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 角色菜单关系表  服务实现类
 * </p>
 *
 * @author YUE
 * @since 2020-05-26
 */
@DubboService
public class SysRoleMenuRelationServiceImpl extends ServiceImpl<SysRoleMenuRelationMapper, SysRoleMenuRelationDTO> implements ISysRoleMenuRelationService {
    @Resource
    private YmlConfig ymlConfig;

    @Autowired
    private SysRoleServiceImpl sysRoleService;

    @Autowired
    private SysMenuServiceImpl sysMenuService;

    /**
     * 用于前端的权限操作相关信息
     * @param sysRoleMenuRelationBO
     * @return
     */
    @Transactional
    @Override
    public boolean updateShopRoleMenu(SysRoleMenuRelationBO sysRoleMenuRelationBO){
        Long roleId = sysRoleMenuRelationBO.getRoleId();
        //去除之前的权限
        deleteByRoleId(roleId);
        //新增添加的权限
        String menuIds = sysRoleMenuRelationBO.getMenuIds();
        String[] menuIdList = menuIds.split(",");
        for (String s : menuIdList) {
            if(StringUtils.isEmpty(s)){
                continue;
            }
            SysRoleMenuRelationSaveBO sysRoleMenuRelationSaveBO = new SysRoleMenuRelationSaveBO();
            sysRoleMenuRelationSaveBO.setRoleId(roleId);
            sysRoleMenuRelationSaveBO.setMenuId(Long.parseLong(s));
            add(sysRoleMenuRelationSaveBO);
        }
        return true;
    }

    @Override
    public boolean add(SysRoleMenuRelationSaveBO saveBO) {
        SysRoleMenuRelationDTO dto = new SysRoleMenuRelationDTO();
        BeanUtils.copyProperties(saveBO,dto);
        Long id = ymlConfig.getPkId();
        dto.setId(id);
        return this.insert(dto);
    }

    /**
     * 对权限进行操作
     * @param boList
     * @return
     */
    @Transactional
    @Override
    public boolean insertOrUpdateRoleMenu(List<SysRoleMenuRelationBO> boList,Long paramRoleId) {
        deleteByRoleId(paramRoleId);//先删除之前有的权限
        for (SysRoleMenuRelationBO bo : boList) {
            Long menuId = bo.getMenuId();
            Long roleId = bo.getRoleId();
            SysRoleMenuRelationDTO sysRoleMenuRelationDTO = getByMenuAndRole(menuId, roleId);
            if(null == sysRoleMenuRelationDTO){
                //新加一条
                sysRoleMenuRelationDTO = new SysRoleMenuRelationDTO();
                BeanUtils.copyProperties(bo,sysRoleMenuRelationDTO);
                Long id = ymlConfig.getPkId();
                sysRoleMenuRelationDTO.setId(id);
                this.insert(sysRoleMenuRelationDTO);
                continue;
            }
            //如果去除权限 这个角色下面的所有的子角色都要去除有这个权限的信息
            updateRoleMenuRelation(bo,sysRoleMenuRelationDTO);
        }
        return true;
    }

    /**
     *  修改权限
     * @param bo
     * @param sysRoleMenuRelationDTO
     */
    private void updateRoleMenuRelation(SysRoleMenuRelationBO bo,SysRoleMenuRelationDTO sysRoleMenuRelationDTO){
        List<String> newCodeList = new ArrayList<>(Arrays.asList(bo.getCode().split(",")));//修改后的权限信息
        List<String> originCodeList = new ArrayList<>(Arrays.asList(sysRoleMenuRelationDTO.getCode().split(",")));//以前的权限信息
        boolean b = originCodeList.removeAll(newCodeList);//获取要去除的权限
        Long menuId = bo.getMenuId();//菜单id
        Long roleId = bo.getRoleId();//角色id
        if(originCodeList.size() > 0){//去除了权限
            //去除子角色的权限
            updateListRoleMenuRelation(roleId,menuId,originCodeList);
        }
        //修改菜单权限关联关系
        SysRoleMenuRelationDTO tempDTO = getByMenuAndRole(menuId, roleId);
        tempDTO.setCode(newCodeList.stream().collect(Collectors.joining(",")));
        updateById(tempDTO);
    }

    /**
     * 去除子角色的权限
     * @param roleId 角色id
     * @param menuId 菜单id
     * @param codeStrList 要去除的权限code集合
     */
    private void updateListRoleMenuRelation(Long roleId,Long menuId,List<String> codeStrList){
        List<SysRoleDTO> sysRoleDTOList = sysRoleService.getRoleListByParentId(roleId);//当前角色的子角色集合
        for (SysRoleDTO sysRoleDTO : sysRoleDTOList) {
            updateListRoleMenuRelation(sysRoleDTO.getId(),menuId,codeStrList);
        }
        SysRoleMenuRelationDTO sysRoleMenuRelationDTO = getByMenuAndRole(menuId, roleId);
        if(null == sysRoleMenuRelationDTO){
            return;
        }
        List<String> originCodeList = new ArrayList<>(Arrays.asList(sysRoleMenuRelationDTO.getCode().split(",")));//以前的权限信息
        if(originCodeList.size() == 0){
            return;
        }
        boolean b = originCodeList.removeAll(codeStrList);
        if(b){//去除过
            //更新信息
            sysRoleMenuRelationDTO.setCode(originCodeList.stream().collect(Collectors.joining(",")));
            updateById(sysRoleMenuRelationDTO);
        }
    }

    /**
     *  修改权限
     * @param bo
     * @param sysRoleMenuRelationDTO
     */
    @Override
    public void updateMenuRelation(SysRoleMenuRelationBO bo,SysRoleMenuRelationDTO sysRoleMenuRelationDTO){
        List<String> newCodeList = new ArrayList<>(Arrays.asList(bo.getCode().split(",")));//修改后的权限信息
        List<String> originCodeList = new ArrayList<>(Arrays.asList(sysRoleMenuRelationDTO.getCode().split(",")));//以前的权限信息
        boolean b = originCodeList.removeAll(newCodeList);//获取要去除的权限
        Long menuId = bo.getMenuId();//菜单id
        Long roleId = bo.getRoleId();//角色id
        if(originCodeList.size() > 0){//去除了权限
            //去除子菜单的权限
            updateListMenuRelation(roleId,menuId,sysMenuService.selectById(menuId).getCode(),originCodeList);
        }
        //修改菜单权限
        SysMenuDTO sysMenuDTO = sysMenuService.selectById(menuId);
        sysMenuDTO.setCode(newCodeList.stream().collect(Collectors.joining(",")));
        sysMenuDTO.setName(bo.getName());
        sysMenuDTO.setUrl(bo.getUrl());
        sysMenuDTO.setNotes(bo.getNotes());
        sysMenuService.updateById(sysMenuDTO);
        //修改菜单权限关联关系
        SysRoleMenuRelationDTO tempDTO = getByMenuAndRole(menuId, roleId);
        tempDTO.setCode(newCodeList.stream().collect(Collectors.joining(",")));
        updateById(tempDTO);
    }

    /**
     * 去除子菜单的权限
     * @param menuId 菜单id
     * @param codeStrList 要去除的权限code集合
     */
    private void updateListMenuRelation(Long roleId,Long menuId,String currentMenuCode,List<String> codeStrList){
        List<SysMenuDTO> sysMenuDTOList = sysMenuService.getByParentId(menuId);
        for (SysMenuDTO sysMenuDTO : sysMenuDTOList) {
            updateListMenuRelation(roleId,sysMenuDTO.getId(),sysMenuDTO.getCode(),codeStrList);
        }
        if(roleId.equals(SysConstant.ADMIN_ID)){//admin的操作 还要把本身菜单 权限更新
            List<String> originCodeList = new ArrayList<>(Arrays.asList(currentMenuCode.split(",")));//以前的权限信息
            if(originCodeList.size() > 0){
                boolean b = originCodeList.removeAll(codeStrList);
                if(b){//去除过
                    //更新信息
                    SysMenuDTO sysMenuDTO = new SysMenuDTO();
                    sysMenuDTO.setId(menuId);
                    sysMenuDTO.setCode(originCodeList.stream().collect(Collectors.joining(",")));
                    sysMenuService.updateById(sysMenuDTO);
                }
            }
        }
        List<SysRoleMenuRelationDTO> sysRoleMenuRelationDTOList = getByMenuId(menuId);
        for (SysRoleMenuRelationDTO sysRoleMenuRelationDTO : sysRoleMenuRelationDTOList) {
            List<String> originCodeList = new ArrayList<>(Arrays.asList(sysRoleMenuRelationDTO.getCode().split(",")));//以前的权限信息
            if(originCodeList.size() == 0){
                continue;
            }
            boolean b = originCodeList.removeAll(codeStrList);
            if(b){//去除过
                //更新信息
                sysRoleMenuRelationDTO.setCode(originCodeList.stream().collect(Collectors.joining(",")));
                updateById(sysRoleMenuRelationDTO);
            }
        }
    }

    /**
     * 根据菜单id和角色id获取信息
     * @param menuId 菜单id
     * @param roleId 角色id
     * @return
     */
    @Override
    public SysRoleMenuRelationDTO getByMenuAndRole(Long menuId,Long roleId){
        Wrapper<SysRoleMenuRelationDTO> wrapper = new EntityWrapper<>();
        wrapper.eq("menu_id",menuId);
        wrapper.eq("role_id",roleId);
        return selectOne(wrapper);
    }

    private List<SysRoleMenuRelationDTO> getByMenuId(Long menuId){
        Wrapper<SysRoleMenuRelationDTO> wrapper = new EntityWrapper<>();
        wrapper.eq("menu_id",menuId);
        return selectList(wrapper);
    }

    /**
     * 根据角色id删除信息
     * @param roleId
     */
    public void deleteByRoleId(Long roleId){
        Wrapper wrapper = new EntityWrapper();
        wrapper.eq("role_id",roleId);
        delete(wrapper);
    }

    /**
     * 根据角色id删除信息
     * @param menuId
     */
    public void deleteByMenuId(Long menuId){
        Wrapper wrapper = new EntityWrapper();
        wrapper.eq("menu_id",menuId);
        delete(wrapper);
    }
}
